#ifndef __FRAMEWORK_GLOBAL_H__
#define __FRAMEWORK_GLOBAL_H__

#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <functional>
#include "framework_complier.h"
#include "framework_config.h"

#define FW_VERSION "1.0"

//名称的长度
#define FW_NAME_MAX_LEN 25

#ifdef  FW_FULL_ASSERT
extern void FW_AssertFailed(uint8_t *file, uint32_t line);
#define FW_ASSERT(expr) ((expr) ? (void)0U : FW_AssertFailed((uint8_t *)__FILE__, __LINE__))
#else
#define FW_ASSERT(expr) ((void)0U)
#endif

#define FW_UNUSED(x) (void)x

//容器操作
#define DelateAll(container)  do{\
    for(auto &it : container)\
    {\
        delete it.second;\
    }\
}while(0)

//数据索引检测 
//二种Index类型：
//从0开始， 从1开始
//二种CHECK 
//模式：CHECK:永久有效  ASSERT:Relase 可屏蔽
#define CHECK_ARRAY_INDEX_COND_0(array, index)  ((int)index >= 0 && (int)index < SIZEOF_ARRAY(array))
#define CHECK_ARRAY_INDEX_0(array, index)  if(!CHECK_ARRAY_INDEX_COND_0(array, index)) return
#define CHECK_ARRAY_INDEX_RET_0(array, index, ret)  if(!CHECK_ARRAY_INDEX_COND_0(array, index)) return ret

#define CHECK_ARRAY_INDEX_COND_1(array, index)  ((int)index > 0 && (int)index <= SIZEOF_ARRAY(array))
#define CHECK_ARRAY_INDEX_1(array, index)  if(!CHECK_ARRAY_INDEX_COND_1(array, index)) return
#define CHECK_ARRAY_INDEX_RET_1(array, index, ret)  if(!CHECK_ARRAY_INDEX_COND_1(array, index)) return ret

#define ASSERT_ARRAY_INDEX_0(array, index)  FW_ASSERT(CHECK_ARRAY_INDEX_COND_0(array, index))
#define ASSERT_ARRAY_INDEX_1(array, index)  FW_ASSERT(CHECK_ARRAY_INDEX_COND_1(array, index))

//唯一 var name
#define private_merge_body(a, b) a ## b
#define private_merge(a, b) private_merge_body(a, b)
#define UniqueVarName(name) private_merge(name, __COUNTER__)


//自动初始化注册机制
#define FW_SECTION(x)  __attribute__((section(x)))
#define FW_USED    __attribute__((used))
typedef void (*fw_init_fn_t)(void);

#define FW_INIT_EXPORT_BY_NAME(name, fn, level) FW_USED const fw_init_fn_t __fw_init##name FW_SECTION(".fw_init_fn."#level) = fn
#define FW_INIT_EXPORT(fn, level) FW_INIT_EXPORT_BY_NAME(fn, fn, level)

//Board初始化，SOC初始化
#define FW_INIT_BOARD_EXPORT(fn)            FW_INIT_EXPORT(fn, 1)
//DEVICE 初始化
#define FW_INIT_DEVICE_EXPORT(fn)           FW_INIT_EXPORT(fn, 3)
//APP初始化
#define FW_INIT_APP_EXPORT(fn)              FW_INIT_EXPORT(fn, 5)


#define FW_INIT_BOARD_EXPORT_LAMDA(name, fn)            FW_INIT_EXPORT_BY_NAME(name, fn, 1)
#define FW_INIT_DEVICE_EXPORT_LAMDA(name, fn)           FW_INIT_EXPORT_BY_NAME(name, fn, 3)
#define FW_INIT_APP_EXPORT_LAMDA(name, fn)              FW_INIT_EXPORT_BY_NAME(name, fn, 5)

//二种注册的方式 [lamda模式更方便]
//1、类模式
class RegisterMetaByClass
{
    using FUNC = std::function<void(void)>;
public:
    explicit RegisterMetaByClass(FUNC func)
    {
        func();
    }
};

//2、lamda模式
#define RegisterMetaByLamda(lamda) lamda();

//字节操作 (小端)
#define PLAT_SET_BYTE(v, indexByte) ((v | (1u << (8*indexByte))))
#define PLAT_GET_BYTE(v, indexByte) ((v >> (8*indexByte)) & 0xFF)

//位操作
#define PLAT_SET_BIT(v, n)  (v | (1u << n))
#define PLAT_CLR_BIT(v, n)  (v & (~(1u << n)))
#define PLAT_CPL_BIT(v, n)  (v ^ (1u << n))
#define PLAT_GET_BIT(v, n)  ((v & (1u << n)) != 0)

//命名空间
#define NAMESPACE_BEGIN(name) namespace name {
#define NAMESPAEC_END  }

#define  STR(v)  #v
#define  STRSTR(v)  STR(v)

#define NEWLINE "\r\n"

#define PLAT_UNUSED(X) (void)X 

//calc array length
#define SIZEOF_ARRAY(arr) (sizeof(arr)/sizeof(arr[0]))

//check type
#define CHECK_TEMPLATE_BASE_OF(T, parent) static_assert(std::is_base_of<parent, T>::value, #T " must baseof " #parent);

#define PLAT_DISABLE_COPY(Class) \
    Class(const Class &) = delete;\
    Class &operator=(const Class &) = delete;

#define PLAT_DISABLE_CONSTRUCTOR(Class) \
    Class() = delete; \


//singleton
#define SINGLETON_DECL(Class) \
    static Class &GetInstance();

#define SINGLETON_IMPL(Class) \
    Class& Class::GetInstance() \
    {\
        static Class ins;\
        return ins;\
    }

#define SINGLETON_DECL_AND_IMPL(Class) \
    inline static Class& GetInstance() \
    {\
        static Class ins;\
        return ins;\
    }
    
//获取成员函数的地址
template<typename dst_type,typename src_type>
dst_type GetClassMemberFunc(src_type src)
{
    union
    {
        src_type s;
        dst_type d;
    }u;
    u.s = src;
    return u.d;
}

#endif // __FRAMEWORK_GLOBAL_H__
